﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.HomeServer.SDK.Interop.v1;
using System.Runtime.InteropServices;
using System.Threading;

namespace Umbrella.Whs
{
    public class WhsNotification
    {
        private static WHSInfo _info;
        private readonly static object _infoCreateLock = new object();
        private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(WhsNotification));
        private static readonly TimeSpan TimerInfinite = new TimeSpan(0, 0, 0, 0, -1);

        private string _id;
        private Timer _timer;
        private bool _isShown;

        public string Id
        {
            get { return _id; }
        }

        public bool IsShown
        {
            get { return _isShown; }
        }

        public WHS_Notification_Severity Severity
        {
            get;
            set;
        }

        public string Title
        {
            get;
            set;
        }

        public string Description
        {
            get;
            set;
        }

        public object Tag
        {
            get;
            set;
        }

        public void UpdateNotifcation()
        {
            if (!_isShown)
            {
                ShowNotification();

                return;
            }

            try
            {
                _info.AddNotification(
                    _id,
                    this.Severity,
                    this.Title ?? string.Empty,
                    this.Description ?? string.Empty,
                    string.Empty,
                    string.Empty,
                    string.Empty
                    );
            }
            catch (COMException)
            {
                // ignore
            }
        }

        public void ShowNotification()
        {
            if (_isShown)
                return;

            if (_log.IsDebugEnabled)
            {
                _log.DebugFormat(
                    "Start showing notification {3}: [{2}] {0}: {1}",
                    this.Title,
                    this.Description,
                    this.Severity,
                    this.Id
                    );
            }

            try
            {
                _info.AddNotification(
                    _id,
                    this.Severity,
                    this.Title ?? string.Empty,
                    this.Description ?? string.Empty,
                    string.Empty,
                    string.Empty,
                    string.Empty
                    );
            }
            catch (COMException)
            {
                // ignore
            }
            finally
            {
                _isShown = true;
            }
        }

        public void ShowNotification(TimeSpan timeToShow)
        {
            try
            {
                // prepare timer
                if (_timer == null)
                {
                    _timer = new Timer(
                        (s) => HideNotification(),
                        null,
                        timeToShow,
                        TimerInfinite
                        );
                }
                else
                {
                    _timer.Change(
                        timeToShow,
                        TimerInfinite
                        );
                }
	
                // inform user
                ShowNotification();
            }
            catch (Exception ex)
            {
                _log.Error("Failed to show notification", ex);

                throw;
            }
        }

        public void HideNotification()
        {
            if (!_isShown)
                return;

            if (_log.IsDebugEnabled)
            {
                _log.DebugFormat(
                    "Stop showing notification {3}: [{2}] {0}: {1}",
                    this.Title,
                    this.Description,
                    this.Severity,
                    this.Id
                    );
            }

            try
            {
                _info.RemoveNotification(_id);
            }
            catch (COMException)
            {
                // ignore
            }
            finally
            {
                _isShown = false;
            }
        }

        public WhsNotification()
            : this(Guid.NewGuid().ToString("N"))
        {

        }

        public WhsNotification(string id)
        {
            if (string.IsNullOrEmpty(id))
                throw new ArgumentException("null or empty", "id");

            // prepare
            _id = id;

            this.Severity = WHS_Notification_Severity.WHS_INFO;

            // connect
            if (_info == null)
            {
                lock (_infoCreateLock)
                {
                    if (_info == null)
                    {
                        _info = new WHSInfoClass();

                        _info.Init(Properties.Constants.ApplicationName);
                    }
                }
            }
        }
    }
}